/*********************************************************************************
 *      Copyright:  (C) 2022 zengwen<1825984037@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  mosquitto_pub3.c
 *    Description:  This file is MQTT publishing side.
 *                 
 *        Version:  1.0.0(31/07/22)
 *         Author:  zengwen <1825984037@qq.com>
 *      ChangeLog:  1, Release initial version on "31/07/22 21:43:48"
 *                 
 ********************************************************************************/
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <libgen.h>
#include <getopt.h>
#include <string.h>
#include <mosquitto.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <signal.h>
#include <time.h>

#include "mqtt_conf.h"
#include "cJSON.h"
#include "dictionary.h"
#include "iniparser.h"
#include "logger.h"
#include "sqlite3.h"
#include "get_massage.h"
#include "data_sqlite3.h"
#include "package_data.h"

#define  PROG_VERSION "1.0.0"
#define  CONF_FILE "./mqtt.ini"

static int g_stop = 0;

int get_time(char cur_time[]);
void print_usage(char *progname);
int judgment_time(int t_interval,time_t last_time);
void sig_handle(int signum);
void connect_callback(struct mosquitto *mosq, void *obj, int rc);

int main(int argc,char *argv[])
{
	struct total_data           mqtt;
	sqlite3                    *db;
	int                         ch;
	int                         rv=-1;
	char                       *progname = NULL;
	char                       *platform;
	struct mosquitto           *mosq = NULL;
	struct option               opts[] = {
		{"platform",required_argument,NULL,'p'},
		{"hlep",no_argument,NULL,'h'},
		{NULL,0,NULL,0}
	};

	progname = basename(argv[0]);

	while((ch=getopt_long(argc,argv,"p:h",opts,NULL))!=-1)
	{
		switch(ch)
		{
			case 'p':
				platform = (optarg);
				break;
			case 'h':
				print_usage(argv[0]);
				return 0;
			default:
				break;
		}
	}

	if(!platform )
	{
		print_usage(progname);
		return 0;
	}
	log_info ("platform=%s\n",platform);

/*  信号捕捉  */
	signal(SIGINT, sig_handle);
	signal(SIGALRM, sig_handle);
	signal(SIGTERM, sig_handle);

	memset(&mqtt,0,sizeof(mqtt));
	rv = get_config(CONF_FILE,&mqtt,platform);

	if(rv< 0)
	{
		printf ("Failed to load the configuration file:%s.\n",strerror(errno));
	}

	/*   创建日志   */
	rv= logger_init(mqtt.common.log_file, mqtt.common.level, mqtt.common.size);

	if(rv < 0)
	{
		fprintf(stderr,"initial logger failure:%s\n",strerror(errno));
		return -1;
	}
	log_info("Logger system initialise ok\n");

	/*  打开数据库  */
	if(open_data_sqlite(&db,mqtt.common.db_file))
	{
		printf ("open database failure:%s\n",strerror(errno));
		return -2;
	}

	mqtt.db = db;

	/*  mqtt初始化 */
	mosquitto_lib_init();

	/* 创建mqtt客户端 */
	mosq = mosquitto_new(mqtt.mqtt.clientid,false,(void *)&mqtt);

	if(! mosq)
	{
		printf("mosquitto_new() failed: %s\n",strerror(errno));
		goto cleanup;
		return -3;
	}
	/*  设置账号密码  */
	if(mosquitto_username_pw_set(mosq,mqtt.mqtt.username,mqtt.mqtt.password) != MOSQ_ERR_SUCCESS)
	{
		printf("mosquitto_username_pw_set failed: %s\n",strerror(errno));
		goto cleanup;
	}
	log_info("Create mosquitto successfully!\n");

	mosquitto_connect_callback_set(mosq,connect_callback);

	while(1)
	{
		if((judgment_time(mqtt.common.t_interval,mqtt.last_time)) )//到采样时间
		{
			if(package_massage(mqtt.msg) < 0)//采样
			{
				printf ("get temperature humidity and current time failure.\n");
			}
			log_info("msg is %sC\n",mqtt.msg);

			time(&mqtt.last_time);
		//	printf ("last_time=%d\n",mqtt.last_time);
			mqtt.flag = 1;
		}
		else
		{
			mqtt.flag = 0;
		}

		if((mqtt.sq_flag = get_data_sqlite(mqtt.db,mqtt.buf ) ) )
		{
			log_info("The database gets the data is %s\n",mqtt.buf);
		}
		else
		{
			log_info("The database is null\n");
			mqtt.sq_flag = 0;
		}

		if(mosquitto_connect(mosq, mqtt.mqtt.brokeraddress,mqtt.mqtt.brokerport,KEEP_ALIVE) != MOSQ_ERR_SUCCESS)
		{
			printf ("connect to server failure.\n");
			goto cleanup;
		}

		sleep(1);
		if(mosquitto_loop_forever(mosq, -1, 1) != MOSQ_ERR_SUCCESS)
		{
			goto cleanup;
		}
	}

cleanup:
	mosquitto_destroy(mosq);
	mosquitto_lib_cleanup();
	return 0;

}

/*连接回调*/
void connect_callback(struct mosquitto *mosq, void *obj, int rc)
{
	struct total_data  *mqtt;

	mqtt =(total_data *)obj;

	if(!rc)
	{
		if(mqtt->flag == 1)//采样了
		{
			if(package_data(mqtt->msg, mqtt->platform) != 0)//打包采样数据
			{
				printf ("failed to package data:%s\n",strerror(errno));
			}
			printf ("%s\n",mqtt->msg);

			if(mosquitto_publish(mosq,NULL,mqtt->mqtt.topic,strlen(mqtt->msg),mqtt->msg,0,true) != MOSQ_ERR_SUCCESS)//发送采样数据
			{
				printf("mosquitto_publish failed: %s\n",strerror(errno));

				if(save_data_sqlite(mqtt->db,mqtt->msg)<0)//保存到数据库
				{
					printf ("insert data failure:%s\n",strerror(errno));
				}
				log_info ("sava data to database suFailed to save data successfully.\n");
			}

			log_info ("send data successfully\n");
			memset(mqtt->msg,0,256);
		}

		if(mqtt->sq_flag == 1)//读数据库保存的数据成功
		{
			printf("数据库获取的数据：%s\n",mqtt->buf);

			if(package_data(mqtt->buf,mqtt->platform) == 0)//打包数据库里的数据
			{
				if(mosquitto_publish(mosq,NULL,mqtt->mqtt.topic,strlen(mqtt->buf),mqtt->buf,0,true) == MOSQ_ERR_SUCCESS)//发送数据库里的数据
				{
					if(delete_data_sqlite(mqtt->db)<0)
					{
						printf ("delete data from databases failure:%s\n",strerror(errno));
					}
					log_info ("delete data from database successfully\n");
				}

				else
				{
					log_err("mosquitto_publish the data from database failed: %s\n",strerror(errno));
				}
			}
		}
		else
		{
			log_info ("database is null,need not to send.\n");
		}
	}
	else
	{
		if(mqtt->flag == 1)
		{
			if(save_data_sqlite(mqtt->db,mqtt->msg) == 0)
			{
				log_info ("client is not connet to server,save data to database successfully.\n");
			}
			else
			{
				log_err ("save data to database failure\n");
				return ;
			}
		}

		if(mqtt->sq_flag == 1)
		{

			log_info ("client is not connet to server,cannot send database data.\n");
		}
	}

	mosquitto_disconnect(mosq);
}

/*  判断是否到采样时间  */
int judgment_time(int t_interval,time_t last_time)
{
	time_t now_time;

	time(&now_time);
//	printf ("now_time=%d\n",now_time);

	if((last_time+t_interval) < now_time )
	{
		printf("start to sampling\n");
		return -1;
	}

	return 0;
}

/*  参数解析  */
void print_usage(char *progname)
{
	printf ("%s usage:\n",progname);
	printf ("-p(--platform):select cloud platform\n");
	printf("-h(--help):print this help information.\n");
	printf ("eg:-p alicloud/tencentcloud/huaweicloud\n");

	return ;
}

/*  安装信号  */
void sig_handle(int signum)
{
	printf("catch signal[%d]\n",signum);
	 g_stop=1;
}

